// 迭代器
// jQuery
$.each([1,2,3], (idx, i) => {
    console.log('下标' + idx);
    console.log('值' + i);
})
// 自我实现一个each方法
const each = (arr, callback) => {
    for (let i = 0; i < arr.length; i++) {
        callback.call(arr[i], i, arr[i])
    }
}
each([1,2,3], (i, n) => {})
// 内部迭代器
// 不能修改内部迭代规则
// 判断2个数组是否完全相等
// const compare = (arr1, arr2) => {
//     if (arr1.length !== arr.length) {
//         throw new Error('不相等');
//     }
//     each(arr1, function(i, n) {
//         if (n !== arr2[i]) {
//             throw new Error('不相等');
//         }
//     })
//     console.log('相等');
// }
// 外部迭代器
const Iterator = function(obj) {
    let current = 0;
    let next = function() {
        current += 1;
    }
    let isDone = function() {
        return current >= obj.length
    }
    let getCurrentItem = function() {
        return obj[current]
    }
    return {
        next,
        isDone,
        getCurrentItem,
        length: obj.length
    }
}
// 基于外部迭代器改写compare
const compare = function(iterator1, iterator2) {
    if (iterator1.length !== iterator2.length) {
        alert('不相等');
    }
    while(!iterator1.isDone() && !iterator2.isDone()) {
        if (iterator1.getCurrentItem() !== iterator2.getCurrentItem()) {
            throw new Error('不相等');
        }
        iterator1.next();
        iterator2.next();
    }
    alert('相等');
}
const iterator1 = Iterator([1,2,3]);
const iteraror2 = Iterator([1,2,4]);
compare(iterator1, iterator2);
// 迭代类数组对象/字面量对象
//  arguments, {'0': 'a', '1': 'b'}
$.each = function (obj, callback) {
    let value;
    let i = 0;
    let length = obj.length;
    let isArray = isArrayLike(obj);
    if (isArray) { // 判断是不是类数组
        for ( ; i < length; i++) {
            value = callback.call(obj[i], i, obj[i])
        }
        if (value === false) {
            break;
        }
    } else {
        for (i in obj) {
            value = callback.call(obj[i], i, obj[i]);
            if (value === false) {
                break;
            }
        }
    }
    return obj;
}
// 倒序迭代器
const reverseEach = function(array, callback) {
    for (let i = array.length; i >=0; i--) {
        callback(i, array[i])
    }
}
// 中止迭代器
const each = function(array, callback) {
    for (let i = 0; i < array.length; i++) {
        if (callback[i, array[i]] === false) {
            break;
        }
    }
}

each([1,2,3,4,5], (i, n) => {
    if (n > 3) {
        return false;
    }
    console.log(n);
})
// 实际举例
// const getUploadComponent = function () {
//     try {
//         return new ActiveXObject('TXFTNActiveX.FYNUpload') // IE
//     } catch(e) {
//         if (supportFlash()) {
//             let str = '<object type="application/x-shockwave-flash"></object>'
//             return $(str).appendTo($('body'));
//         } else {
//             let str = '<input type="file" name="file" />'
//             return $(str).appendTo($('body'));
//         }
//     }
// }

const getActiveUploadObject = function () {
    try {
        return new ActiveXObject('TXFTNActiveX.FYNUpload')
    } catch (e) {
        return false;
    }
}

const getFlashUploadObject = function () {
    if (supportFlash()) {
        let str = '<object type="application/x-shockwave-flash"></object>';
        return $(str).appendTo($('body'));
    }
    return false;
}

const getFormUploadObject = function () {
    let str = '<input type="file" name="file" />';
    return $(str).appendTo($('body'));
}

const iteratorUploadObject = function () {
    let fn;
    for (let i = 0; fn = arguments[i]; i++) {
        let uploadObject = fn();
        if (uploadObject) {
            return uploadObject
        }
    }
}

const getWebkitUploadObject = function () {
    // ...
}

const getHTML5UploadObject = function () {
    // ...
}

const uploadObject = iteratorUploadObject(getActiveUploadObject, getFlashUploadObject, getFormUploadObject, getWebkitUploadObject, getHTML5UploadObject);


// 发布订阅
// 一对多
document.body.addEventListener('click', () => {
    console.log('click')
});
document.body.addEventListener('click', () => {
    console.log('click2')
});
document.body.addEventListener('click', () => {
    console.log('click3')
});
document.body.addEventListener('click', () => {
    console.log('click4')
});
document.body.click(); // dispatchEvent IE -> fireEvent

// 手动实现一个发布订阅
const saleOffices = {}; // 定义售楼处 -> 发布者
saleOffices.clientList = []; // 缓存列表 存放订阅者回调函数
saleOffices.listen = (key, fn) => {
    if (!this.clientList[key]) {
        this.clientList[key] = [];
    }
    this.clientList[key].push(fn);
}
saleOffices.trigger = () => {
    const key = Array.prototype.shift.call(arguments); // 取出消息类型
    let fns = this.clientList[key];

    if (!fns || fns.length === 0) {
        return;
    }

    for (let i = 0; i < fns.length; i++) {
        let fn = fns[i];
        fn.apply(this, arguments)
    }
}

saleOffices.listen('80', function(price) { // 小明的订阅
    console.log(price + ' ' + squqreMeter);
})

saleOffices.listen('100', function(price) { // 小白的订阅
    console.log(price + ' ' + squqreMeter);
})

saleOffices.trigger('80', 2000000);
saleOffices.trigger('100', 3000000);

// 通用的发布订阅功能
const event = {
    clientList: [],
    listen: function(key, fn) {
        if (!this.clientList[key]) {
            this.clientList[key] = []
        }
        this.clientList[key].push(fn);
    },
    trigger: function() {
        const key = Array.prototype.shift.call(arguments);
        let fns = this.clientList[key];
        if (!fns || fns.length === 0) {
            return;
        }

        for (let i = 0; i < fns.length; i++) {
            let fn = fns[i];
            fn.apply(this, arguments)
        }
    },
    remove: function(key, fn) {
        let fns = this.clientList[key];
        if (!fns) {
            return;
        }
        if (!fn) {
            fns && (fns.length = 0)
        } else {
            for (let i = fns.length; i >=0; i--) {
                let _fn = fns[i];
                if (_fn === fn) {
                    fns.splice(i, 1)
                }
            }
        }
    }
}

const installEvent = function(obj) {
    for (let i in event) {
        obj[i] = event[i]
    }
}

const saleOffice1 = {};
installEvent(saleOffice1);

// 登录实例
// 传统
login.success(function(data) {
    header.setAvatar(data);
    nav.setAvatar(data);
    message.refresh();
    cart.refresh();
    address.refresh();
})
// 发布订阅
$.ajax('http://login', (data) => {
    login.trigger('loginSuccess', data);
})
const header = (function() {
    login.listen('loginSuccess', function(data) {
        header.setAvatar(data);
    });
    return {
        setAvatar: function() {
            console.log('set success');
        }
    }
})();

const nav = (function () {
    login.listen('loginSuccess', function(data) {
        nav.setAvatar(data);
    });
    return {
        setAvatar: function() {
            console.log('set success');
        }
    }
})();

const address = (function () {
    login.listen('loginSuccess', function() {
        address.refresh();
    });
    return {
        refresh: function() {
            console.log('refresh success');
        }
    }
})();

// 全局的中介
const Event = (function() {
    const clientList = [];
    let listen;
    let trigger;
    let remove;

    listen = function(key, fn) {
        if (!clientList[key]) {
            clientList[key] = []
        }
        clientList[key].push(fn);
    }

    trigger = function() {
        const key = Array.prototype.shift.call(arguments);
        let fns = clientList[key];
        if (!fns || fns.length === 0) {
            return;
        }

        for (let i = 0; i < fns.length; i++) {
            let fn = fns[i];
            fn.apply(this, arguments)
        }
    }

    remove = function(key, fn) {
        let fns = clientList[key];
        if (!fns) {
            return;
        }
        if (!fn) {
            fns && (fns.length = 0)
        } else {
            for (let i = fns.length; i >=0; i--) {
                let _fn = fns[i];
                if (_fn === fn) {
                    fns.splice(i, 1)
                }
            }
        }
    }

    return {
        listen,
        trigger,
        remove
    }
})()

Event.listen('squareMeter80', (price) => {
    console.log('价格 = ' + price);
});

Event.trigger('squareMeter80', 2000000);

// 命令模式
let bindClick = function(btn, func) {
    btn.onclick = func;
}

let MenuBar = {
    refresh: function() {
        console.log('MenuBar refresh');
    }
}
let SubMenu = {
    add: function() {
        console.log('sub add');
    },
    del: function() {
        console.log('sub del');
    }
}

bindClick(button1, MenuBar.refresh);
bindClick(button2, SubMenu.add);
bindClick(button3, SubMenu.del);

// 闭包
let setCommand = function(btn, func) {
    btn.onclick = function() {
        func();
    }
}

let MenuBar = {
    refresh: function() {
        console.log('MenuBar refresh');
    }
}

let RefreshMenuBarCommand = function(receiver) {
    return function() {
        receiver.refresh();
    }
}
let refreshMenuBarCommand = new RefreshMenuBarCommand(MenuBar);
setCommand(button1, refreshMenuBarCommand);

// Macro
let closeDoorCommand =  { // 智能命令
    execute: function () {
        console.log('关门');
    }
}

let openComputerCommand = {
    execute: function() {
        console.log('开电脑');
    }
}

let openWXCommand = {
    execute: function() {
        console.log('打开微信');
    }
}

let MacroCommand = function() {
    return {
        commandList: [],
        add: function(command) {
            this.commandList.push(command);
        },
        execute: function() {
            for (let i = 0; i < this.commandList.length; i++) {
                const command = this.commandList[i];
                command.execute();
            }
        }
    }
}

let macro = new MacroCommand();
macro.add(closeDoorCommand);
macro.add(openComputerCommand);
macro.add(openWXCommand);

macro.execute();